import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Set;

import org.eclipse.swt.events.PaintEvent;



/*** Simulation class - is in charge of a dynamic array of robots ***/
public class Simulation {
	
	//Hash map of robots - keys are the robots names in map
	private HashMap<String,Robot> roboMap;
	//amount of robots currently in map
	private int amount = 0;
	//robot factory - hash map of robot factories that creates robots according to name
	RobotFactory roboFact;
	//boxes
	protected Boxes boxes;
	
	
	//constructor
	Simulation(){
		roboMap = new HashMap<String,Robot>();//create robot hash map
		roboFact = new RobotFactory();//create robot factory
		boxes = new Boxes();
	}
	
	//function returns true if robot exists in map and false otherwise
	public boolean nameExists(String name){ return roboMap.containsKey(name);}
	
	//function returns true if type of robot exists
	public boolean TypeExists(String type){ return roboFact.exists(type);}
	
	//function returns if addition exists
	public boolean addExists(String add){ return roboFact.addExists(add);}
	
	//returns robot with requested name
	public Robot getRobot(String name){
		return roboMap.get(name);
	}
	
	public Robot createRobot(String type, String name, int x, int y){
		return roboFact.createRobot(type, name, new Position(x,y)); 
	}
	
	private Robot createRobot(String type, String inner_type, String name, int x, int y){
		return roboFact.createRobotWithAdd(type, inner_type, name, new Position(x,y)); 
	}
	
	//inserts robot to hash map and returns the amount of robots
	public Robot insertRobot(Robot robot)
	{	
		//add new robot to map
		roboMap.put(robot.getName(), robot);
		amount++;

		//return index of inserted robot = last index
		return robot;
	}
	
	//inserts robot to hash map and returns the amount of robots
	public Robot insertRobot(String type, String name, int x, int y)
	{
		Robot robot = createRobot(type, name, x, y);
		
		//add new robot to map
		roboMap.put(name, robot);
		amount++;

		//return index of inserted robot = last index
		return robot;
	}
	
	//for robot with addition: inserts robot to hash map and returns the amount of robots
	public Robot insertRobot(String type, String inner_type, String name, int x, int y)
	{
		//type is addition type, and inner type is basic type of robot
		Robot robot = createRobot(type, inner_type, name, x, y);
		
		//add new robot to map
		roboMap.put(name, robot);
		amount++;

		//return index of inserted robot = last index
		return robot;
	}
	
	/*function prints list of robots according to the distance between their starting
	and current point*/
	public void printByDistance(){
		class Rcomparator implements Comparator<Robot>{
			public int compare(Robot a, Robot b) {
				//return comparison of 2 doubles
				return( new Double(a.getDistance()).compareTo(new Double(b.getDistance())));
			}
		}
		//create priority queue of all robots using Rcomporator
		PriorityQueue<Robot> p = new PriorityQueue<Robot>(roboMap.size(),new Rcomparator());
		p.addAll(roboMap.values());
		
		//print robots from smallest distance to largest
		for(int i = 1; p.size() > 0; i++){
			Robot robot = p.poll();
			System.out.println(i + ". " + robot.getName() +  " distance " + robot.getDistance() );
		}
	}
	
	//prints list of robots lexicographicaly 
	public void printByName(){
		
		//create array list and insert all robots
		ArrayList<Robot> array = new ArrayList<Robot>(roboMap.size());
		array.addAll(roboMap.values());
		
		//sort array (uses comparable which compares names)
		Collections.sort(array);
		//print all robots
		Iterator<Robot> it = array.iterator();
		for(int i = 1; it.hasNext() ; i++){
			System.out.println(i + ". " + it.next().getName());
		}
	}
	
	//returns string set - names of robots
	public Set<String> getAllRobotNames(){ return roboMap.keySet(); }
	
	//returns robot in radius of 20  of x,y 
	public Robot getRobotAt(Position p){
	
		Robot r = null;
		Set<String> strings = roboMap.keySet();
		Iterator<String> it = strings.iterator();
		while(it.hasNext()){
			r = roboMap.get(it.next());
			int r_x = r.getCurrentPosition().x;
			int r_y = r.getCurrentPosition().y;
			System.out.println(p.x +" " +p.y +" , " + r_x +" " + r_y);
			if((Math.abs(p.x - r_x) <= 10) && (Math.abs(p.y - r_y) <= 10))
				return r;
		}
		return null;
	}

}
 